package com.ssy.lingxi.order.serviceimpl.base;

import com.ssy.lingxi.common.constant.marketing.ActivityTypeEnum;
import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.constant.order.OrderSourceKindEnum;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.OrderDO;
import com.ssy.lingxi.order.entity.OrderProductDO;
import com.ssy.lingxi.order.entity.OrderPromotionDO;
import com.ssy.lingxi.order.model.constant.OrderServiceContants;
import com.ssy.lingxi.order.model.dto.OrderSeparateDTO;
import com.ssy.lingxi.order.model.vo.basic.request.OrderPromotionVO;
import com.ssy.lingxi.order.model.vo.vendor.response.VendorOrderProductPromotionVO;
import com.ssy.lingxi.order.repository.OrderPromotionRepository;
import com.ssy.lingxi.order.service.base.IBaseOrderPromotionService;
import com.ssy.lingxi.order.utils.NumberUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单商品关联的营销活动相关接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-09-23
 */
@Service
public class BaseOrderPromotionServiceImpl implements IBaseOrderPromotionService {
    @Resource
    private OrderPromotionRepository orderPromotionRepository;

    /**
     * （拆单）根据拆单订单商品金额总和，加权平均计算拆单后的营销活动金额
     *
     * @param promotionAmount    订单营销活动金额
     * @param promotionAmountMap 拆单订单商品金额总和
     * @return 拆单订单营销活动金额
     */
    @Override
    public Map<OrderSeparateDTO, BigDecimal> findSeparateOrderPromotionAmount(BigDecimal promotionAmount, Map<OrderSeparateDTO, BigDecimal> promotionAmountMap) {
        if(NumberUtil.isNullOrZero(promotionAmount)) {
            return promotionAmountMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, p -> BigDecimal.ZERO));
        }

        BigDecimal totalAmount = promotionAmountMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        if(totalAmount.compareTo(BigDecimal.ZERO) == 0) {
            return promotionAmountMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, p -> BigDecimal.ZERO));
        }

        return promotionAmountMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, p -> p.getValue().multiply(promotionAmount).divide(totalAmount, 2, RoundingMode.HALF_UP)));
    }

    /**
     * 检查并保存订单商品关联的营销活动
     *
     * @param orderProduct 订单商品
     * @param promotions   营销活动列表
     * @return 操作结果
     */
    @Override
    public Wrapper<Void> checkProductPromotions(OrderProductDO orderProduct, List<OrderPromotionVO> promotions) {
        if(CollectionUtils.isEmpty(promotions)) {
            orderProduct.setPromotions(new HashSet<>());
            return Wrapper.success();
        }

        List<OrderPromotionDO> orderPromotions = promotions.stream().map(p -> {
            OrderPromotionDO promotion = new OrderPromotionDO();
            promotion.setRecordId(NumberUtil.isNullOrNegative(p.getRecordId()) ? 0L : p.getRecordId());
            promotion.setProduct(orderProduct);
            promotion.setPromotionId(p.getPromotionId());
            promotion.setName(p.getName());
            promotion.setPromotionType(p.getPromotionType());
            promotion.setBelongType(p.getBelongType());
            promotion.setStartTime(LocalDateTime.parse(p.getStartTime(), OrderServiceContants.DEFAULT_TIME_FORMATTER));
            promotion.setExpireTime(LocalDateTime.parse(p.getExpireTime(), OrderServiceContants.DEFAULT_TIME_FORMATTER));
            return promotion;
        }).collect(Collectors.toList());

        orderPromotionRepository.saveAll(orderPromotions);

        orderProduct.setPromotions(new HashSet<>(orderPromotions));
        return Wrapper.success();
    }

    /**
     * 查询订单商品营销活动记录
     *
     * @param orderProduct 订单商品
     * @return 查询结果
     */
    @Override
    public Wrapper<List<VendorOrderProductPromotionVO>> findOrderProductPromotions(OrderProductDO orderProduct) {
        return Wrapper.success(orderPromotionRepository.findByProduct(orderProduct).stream().map(promotion -> {
            VendorOrderProductPromotionVO promotionVO = new VendorOrderProductPromotionVO();
            promotionVO.setPromotionId(promotion.getPromotionId());
            promotionVO.setName(promotion.getName());
            promotionVO.setPromotionType(promotion.getPromotionType());
            promotionVO.setPromotionTypeName(ActivityTypeEnum.getMessage(promotion.getPromotionType()));
            promotionVO.setBelongType(promotion.getBelongType());
            promotionVO.setBelongTypeName(BelongTypeEnum.getCodeMessage(promotion.getBelongType()));
            promotionVO.setStartTime(promotion.getStartTime().format(OrderServiceContants.DEFAULT_TIME_FORMATTER));
            promotionVO.setExpireTime(promotion.getExpireTime().format(OrderServiceContants.DEFAULT_TIME_FORMATTER));
            return promotionVO;
        }).collect(Collectors.toList()));
    }

    /**
     * 查询拼团订单的拼团Id
     *
     * @param order 订单
     * @return 拼团Id
     */
    @Override
    public Long findGroupOrderRecordId(OrderDO order) {
        if(!order.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode())) {
            return 0L;
        }

        return order.getProducts().stream().flatMap(p -> p.getPromotions().stream()).map(OrderPromotionDO::getRecordId).findFirst().orElse(0L);
    }
}
